byte-data
Pack and unpack binary data.
Copyright (c) 2017-2018 Rafael da Silva Rocha.
https://github.com/rochars/byte-data
byte-data is a ES module to pack and unpack numbers and strings to and from byte buffers.
- MIT licensed
- Type safe
- Compatible with IE6+ and browsers that support ES3/ES5/ES6+
- Use it out of the box in Node.js
- Use it out of the box with TypeScript
- Tested in little-endian and big-endian machines!
- Can be used where typed arrays can't
- Less than 6kb minified!
Pack/unpack:
- Integers, unsigned and signed (two's complement)
- 16-bit half-precision floating-point numbers
- 32-bit single-precision floating-point numbers
- 64-bit double-precision floating-point numbers
- Little-endian and big-endian words
- UTF-8 strings (1 to 4 bytes per character, invalid characters are replaced)
Install
npm install byte-data
Browser
Use byte-data.umd.js in the /dist folder of this package:
<script src="./dist/byte-data.umd.js"></script>
<script>
var packed = byteData.pack(2.1474836, {bits: 32, fp: true});
</script>
Or load it from the jsDelivr CDN:
<script src="https://cdn.jsdelivr.net/npm/byte-data"></script>
Or load it from unpkg:
<script src="https://unpkg.com/byte-data"></script>
Browser compatibility
The UMD dist (./dist/byte-data.umd.js) is transpiled to ES3 and compatible with IE6+. Should work in all modern browsers that support ES3/ES5/ES6+.
Cross-browser tests powered by
Node
import * as byteData from 'byte-data';
byteData.packTo(1077, {bits: 16, signed: true}, buffer, 4);
let packed = byteData.pack(128, {bits: 8});
Or import just what you need:
import {pack} from 'byte-data';
let packed = pack(128, {bits: 8});
Or require:
const byteData = require('byte-data');
let packed = byteData.pack(2.1474836, {bits: 32, fp: true});
About
pack and packTo
pack(num, theType) will return a Array with the bytes of the passed value.
let packed = pack(123, {bits: 16});
packTo(num, theType, buffer, index) will write the bytes of the number to the provided buffer (Uint8Array or Array), start writing on index.
let buffer = new Uint8Array(4);
packTo(402, {bits: 16}, buffer, 2);
index can be ommited and will default to zero:
let buffer = new Uint8Array(4);
packTo(402, {bits: 16}, buffer);
Packing null, false, true and undefined
- Packing undefined values throw 'Undefined value' error
- null and false are packed as 0
- true is packed as 1
Unpacking and input buffer length
- When unpacking a single value, a 'Bad buffer length' error is throw if the number of bytes is not sufficient (Ex: unpack a 32-bit number, but provide a input buffer with length smaller than 4)
- When unpacking a array of values, extra bytes in the end of the buffer are ignored and insufficient bytes will return a empty array by default:
byteData.unpackArray([0xff], {bits: 16}, 0, 1);
byteData.unpackArray([0xff, 0xff, 0xff], {bits: 16}, 0, 3);
You can unpack arrays in safe mode with the optional safe param set to true. In safe mode insufficient bytes in the input array or extra bytes in the end of the input array will cause a 'Bad buffer length' error:
byteData.unpackArray([0xff], {bits: 16}, 0, 1, true);
byteData.unpackArray([0xff, 0xff, 0xff], {bits: 16}, 0, 3, true);
Floating-point numbers
- Floating-point numbers are IEEE 754 standard.
- Overflows are rounded towards Infinity and -Infinity.
- NaN is packed as quiet NaN. Both quiet NaN and signaling NaN can be unpacked.
- Support packing and unpacking negative zeros.
- Support packing and unpacking Infinity and negative Infinity
Minifloats
Currently only 16-bit half-precision.
Integers
- Overflow on integers will throw a "Overflow" error.
- packing NaN will throw a 'NaN' error.
- packing Infinity or -Infinity will throw a 'Overflow' error.
Signed integers
Signed integers are two's complement.
Strings
UTF-8 strings with 1 to 4 bytes per character can be packed and unpacked. BOM is kept untouched if present. Invalid characters are replaced with Unicode Character 'REPLACEMENT CHARACTER' (U+FFFD).
Reading strings from buffers
Use unpackString(buffer, index, end). The paramters index and end determine a slice of the buffer to read. So to read the first 4 bytes of a buffer:
let str = unpackString(buffer, 0, 3);
If index and end are ommited unpackString(buffer) will read the entire buffer:
let str = unpackString(buffer);
Writing strings to buffers
packStringTo(str, buffer, index=0) will write the string to the provided buffer (Uint8Array or Array), starting on the index. Index defaults to zero if ommited (start from the beginning of the buffer).
let buffer = [];
packStringTo(str, buffer);
Packing strings to Uint8Array buffers
If you need to calculate the buffer length before writing you may use the utf8-buffer-size module:
import utf8BufferSize from 'utf8-buffer-size';
let buffer = new Uint8Array(utf8BufferSize(str));
packStringTo(str, buffer);
Types
Types are user-defined objects like this:
const binary32 = {
bits: 32,
signed: true,
fp: true,
be: false
}
Tests on big-endian systems
Use QEMU with this PowerPC/Debian image:
https://people.debian.org/~aurel32/qemu/powerpc/
API
function unpackString(buffer, index=0, len=null) {}
function packString(str) {}
function packStringTo(str, buffer, index=0) {}
function pack(value, theType) {}
function packTo(value, theType, buffer, index=0) {}
function packArray(values, theType) {}
function packArrayTo(values, theType, buffer, index=0) {}
function unpack(buffer, theType, index=0) {}
function unpackArray(
buffer, theType, index=0, end=buffer.length, safe=false) {}
function unpackArrayTo(
buffer, theType, output, index=0, end=buffer.length, safe=false) {}
Contributing
byte-data welcomes all contributions from anyone willing to work in good faith with other contributors and the community. No contribution is too small and all contributions are valued.
See CONTRIBUTING.md for details.
Style guide
byte-data code should follow the Google JavaScript Style Guide:
https://google.github.io/styleguide/jsguide.html
Code of conduct
This project is bound by a code of conduct: The Contributor Covenant, version 1.4, also available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting rocha.rafaelsilva@gmail.com.
Legal
LICENSE
Copyright (c) 2017-2018 Rafael da Silva Rocha.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.